<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>闭包</title>
</head>
<body>
<!-- 
    闭包使用场景：https://www.jb51.net/article/203104.htm
 -->
</body>
<script>
    // 示例
    function fn1(){
        var n = 1  // > 也就是执行到这一行，就有fn2函数对象了，因为在fn1执行前，在预编译里就执行了函数定义，产生了函数执行上下文
        var m = 2
        function fn2(){ // 在函数定义时就产生了闭包，不用调用内部函数
            console.log(n)       
        } 
    }
    fn1()    

    /*
        闭包如何产生？
            当一个嵌套的内部函数引用了嵌套的外部函数中的变量就产生了闭包。
        闭包是什么？
            嵌套的内部函数对象 （多数人）
            内部函数中包含被引用变量的对象 （少数人）
            * 在chrome里调试：在'let n = 1'行打断点，就已经产生了fn2函数对象，
                            看fn2函数对象中的scoped，有一个closure对象，就是闭包
        闭包产生的两个条件：
            1. 函数嵌套
            2. 内部函数使用了外部函数中的变量
            3. 外部函数执行
    */

    // 闭包终极面试题
    function fun(n, o){
        console.log(o)
        return {
            fun: function(m){
                return fun(m,n)
            }
        }
    }
    var a = fun(0) // undefined  产生了一个闭包，属性n，值为0
    a.fun(1) // 0  由于fun外部函数再次执行，也产生了新的闭包，但是由于没有接收，执行完就消失了
    a.fun(2) // 0  同上
    a.fun(3) // 0  同上

    var b = fun(0).fun(1).fun(2).fun(3) // undefined，0，1，2

    var c = fun(0).fun(1) // undefined， 0
    c.fun(2) // 1
    c.fun(3) // 1
    
    

    
</script>
</html>